package com.tianhua.amis4j.service.engine;

import com.coderman.model.meta.bean.PlantUMLApiContextBean;
import com.coderman.model.meta.bean.TemplateJsonBean;
import com.coderman.model.meta.bean.back.*;
import com.coderman.model.meta.bean.container.ContainerBean;
import com.coderman.model.meta.bean.dsl.CodeFactoryService;
import com.coderman.model.meta.bean.dsl.ITemplateParse;
import com.coderman.model.meta.engine.WebCodeGenerator;
import com.coderman.model.meta.enums.CodeFileTypeEnum;
import com.coderman.model.meta.enums.CodeLevelEnum;
import com.tianhua.amis4j.service.ability.ReadTemplateWebJsonDocService;
import com.tianhua.amis4j.service.admin.ProjectConfigService;
import com.tianhua.amis4j.service.admin.WebCodeService;
import com.tianhua.amis4j.service.admin.WebCodeTemplateConfigService;
import com.tianhua.amis4j.service.domain.ContainerFactory;
import com.tianhua.amis4j.service.enums.WebArchAppEnum;
import com.tianhua.amis4j.service.parser.ApiMetaDataFactory;
import com.tianhua.amis4j.service.utils.FreemarkerUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;

import java.io.FileNotFoundException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * Description:
 * date: 2022/4/8
 *
 * @author fanchunshuai
 * @version 1.0.0
 * @since JDK 1.8
 */

@Service
public class WebCodeGeneratorImpl implements WebCodeGenerator {

    private static final Logger logger = LoggerFactory.getLogger(WebCodeGeneratorImpl.class);

    @Autowired
    private ContainerFactory containerFactory;

    @Autowired
    private ReadTemplateWebJsonDocService readTemplateWebJsonDocService;

    @Autowired
    private WebCodeService webDslConfigService;


    @Autowired
    private ITemplateParse templateParse;

    @Autowired
    private CodeFactoryRoute codeFactoryRoute;


    @Autowired
    private WebCodeTemplateConfigService webCodeTemplateConfigService;

    @Autowired
    private ApiMetaDataFactory apiMetaDataFactory;

    @Autowired
    private ProjectConfigService projectConfigService;


    @Override
    public void createWebCode(PlantUMLApiContextBean plantUMLApiContextBean) {

        //应用框架处理策略路由
        CodeFactoryService codeFactoryService = codeFactoryRoute.getByWebArchName(plantUMLApiContextBean.getWebArchName());
        //基于api构建web页面容器
        for (ApiBean apiBean : plantUMLApiContextBean.getApiBeanList()){
            buildWebContainerBean(apiBean, plantUMLApiContextBean);
        }

        Map<String,List<ContainerBean>> moduleDslContainerMap = plantUMLApiContextBean.getModuleDslContainerMap();
        for (Map.Entry<String,List<ContainerBean>> entry : moduleDslContainerMap.entrySet()){
            entry.getValue().forEach(containerBean -> {

                String webDslJsonStr = codeFactoryService.buildWebCode(containerBean,plantUMLApiContextBean);
                TemplateJsonBean templateJsonBean = new TemplateJsonBean();
                templateJsonBean.setApiFieldList(webDslJsonStr);
                templateJsonBean.setApiTitle(containerBean.getApiBean().getApiDoc());
                templateJsonBean.setApiUrl(containerBean.getApiBean().getApiUrl());
                if(containerBean.getContainer() != null){
                    templateJsonBean.setContainerTemplateName(containerBean.getContainer().getContainerName());
                }
                plantUMLApiContextBean.addDslJson(entry.getKey(),templateJsonBean);
                logger.info(webDslJsonStr);
            });
        }
        //具体构建webdsljson
        buildWebDslJson(plantUMLApiContextBean);
        ExecutorService executor1 = Executors.newSingleThreadExecutor();
        executor1.execute(()->{
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            templateParse.parse(plantUMLApiContextBean);
        });


    }

    @Override
    public void createWebCode(CreateCodeConfigBean createCodeConfigBean) {
        //1. 根据api选定的模版进行代码生成
        //2. 将生成的代码持久化
        List<ApiBean> apiBeanList = createCodeConfigBean.getApiList();
        ProjectSnapShotBean snapShotBean = projectConfigService.buildProjectSnapShotBean(createCodeConfigBean.getProjectCode());
        createCodeConfigBean.setProjectSnapShotBean(snapShotBean);

        Map<String,Object> templateVarValueMap = apiMetaDataFactory.buildApiMetaDataMap(createCodeConfigBean);

        List<WebCodeTemplateBean> webCodeTemplateBeanList = webCodeTemplateConfigService.getByWebAppName(createCodeConfigBean.getWebAppName());
        Map<String,WebCodeTemplateBean> webCodeTemplateBeanMap = webCodeTemplateBeanList.stream().collect(Collectors.toMap(WebCodeTemplateBean::getTemplateName,o->o));

        for (ApiBean apiBean : apiBeanList){
            if(StringUtils.isEmpty(apiBean.getTemplateName())){
                continue;
            }
            WebCodeTemplateBean webCodeTemplateBean = webCodeTemplateBeanMap.get(apiBean.getTemplateName());
            String ftmlTemplateFilePath = webCodeTemplateBean.getWebArchName() + "/" + webCodeTemplateBean.getTemplateName();
            String templateContent = FreemarkerUtils.parseTpl(ftmlTemplateFilePath,templateVarValueMap);
            WebCodeBean webCodeBean = new WebCodeBean();
            webCodeBean.setWebDslJson(templateContent);
            webCodeBean.setModuleCode(createCodeConfigBean.getModuleCode());
            webCodeBean.setApiUrl(apiBean.getApiUrl()+"."+apiBean.getMethodType());
            webCodeBean.setProjectCode(createCodeConfigBean.getProjectCode());
            webCodeBean.setVersion("v1");
            webCodeBean.setContentType(webCodeTemplateBean.getOutCodeType());
            webCodeBean.setCodeLevel(CodeLevelEnum.API.getLevel());
            webDslConfigService.saveWebDslConfig(webCodeBean);
        }
    }

    /**
     * 构建web容器
     * @param apiBean
     * @param plantUMLApiContextBean
     * @return
     */
    private void buildWebContainerBean(ApiBean apiBean, PlantUMLApiContextBean plantUMLApiContextBean){
        ContainerBean containerBean = new ContainerBean();
        //todo rule config 规则化
        if(apiBean.isGet() && apiBean.getApiUrl().contains("page")){
            containerBean.setContainer(containerFactory.getPageListContainer(plantUMLApiContextBean.getWebArchName()));
        }

        else if(apiBean.isPost() && apiBean.getApiUrl().contains("save")){
            containerBean.setContainer(containerFactory.getInsertFormContainer(plantUMLApiContextBean.getWebArchName()));
        }

        else if(apiBean.isPost() && apiBean.getApiUrl().contains("update")){
            containerBean.setContainer(containerFactory.getUpdateFormContainer(plantUMLApiContextBean.getWebArchName()));
        }

        else if(apiBean.isGet() && apiBean.getApiUrl().contains("get")){
            containerBean.setContainer(containerFactory.getDetailFormContainer(plantUMLApiContextBean.getWebArchName()));
        }

        containerBean.setApiBean(apiBean);
        plantUMLApiContextBean.addContainer(apiBean.getModuleCode(), containerBean);
    }

    /**
     * 构建web dsl json数据--只支持到内置到项目里配置的模版
     * @param plantUMLApiContextBean
     */
    public void buildWebDslJson(PlantUMLApiContextBean plantUMLApiContextBean){
        Map<String, List<TemplateJsonBean>> templateJsonMap = plantUMLApiContextBean.getModuleDslJsonMap();
        for (Map.Entry<String,List<TemplateJsonBean>> entry : templateJsonMap.entrySet()){
            for (TemplateJsonBean templateJsonBean : entry.getValue()){
                List<String> jsonTemplateList = readTemplateWebJsonDocService.readDslJsonContent(plantUMLApiContextBean.getWebArchName(),templateJsonBean.getContainerTemplateName());
                if(jsonTemplateList == null || jsonTemplateList.isEmpty()){
                    logger.error("未找到对应webdsljson模版........apiUrl = {},containerTemplateName = {}",templateJsonBean.getApiUrl(),templateJsonBean.getContainerTemplateName());
                    continue;
                }
                StringBuilder jsonStrBuilder = new StringBuilder();
                for (String jsonStr : jsonTemplateList){
                    String tempJsonStr = jsonStr;
                    tempJsonStr = tempJsonStr.replace("$apiUrl", templateJsonBean.getApiUrl().trim());
                    tempJsonStr = tempJsonStr.replace("$apiTitle", templateJsonBean.getApiTitle().trim());
                    if(StringUtils.isNotEmpty(templateJsonBean.getApiFieldList())){
                        tempJsonStr = tempJsonStr.replace("\"$apiFieldList\"", templateJsonBean.getApiFieldList());
                        tempJsonStr = tempJsonStr.replace("$apiFieldList", templateJsonBean.getApiFieldList());
                    }
                    jsonStrBuilder.append(tempJsonStr+"\n");
                }

                WebCodeBean webCodeBean = new WebCodeBean();
                webCodeBean.setWebDslJson(jsonStrBuilder.toString());
                webCodeBean.setModuleCode(entry.getKey());
                webCodeBean.setApiUrl(templateJsonBean.getApiUrl());
                webCodeBean.setProjectCode(plantUMLApiContextBean.getProjectCode());
                webCodeBean.setVersion("v1");
                if(WebArchAppEnum.AMIS.getAppCode().equals(plantUMLApiContextBean.getWebArchName())){
                    webCodeBean.setContentType(CodeFileTypeEnum.JSON.getCodeType());
                }

                if(WebArchAppEnum.VUE_ELEMENT_UI.getAppCode().equals(plantUMLApiContextBean.getWebArchName())){
                    webCodeBean.setContentType(CodeFileTypeEnum.VUE.getCodeType());
                }

                webCodeBean.setCodeLevel(CodeLevelEnum.API.getLevel());
                webDslConfigService.saveWebDslConfig(webCodeBean);
            }
        }
    }

}
